/*
 * $Id: log.h,v 1.32 2006-02-06 15:01:15 bacon Exp $
 */

#ifndef _XP_UTL_LOG_H_
#define _XP_UTL_LOG_H_

#include <xp/types.h>
#include <xp/macros.h>
#include <xp/bas/mtx.h>

/* TODO: improve this and complete win32 portion */

#define XP_LOG_MSG_MAX   2048
#define XP_LOG_IDENT_MAX 32

/*
 * MACROS: target
 * - XP_LOG_CONSOLE
 * - XP_LOG_FILE
 * - XP_LOG_SYSLOG
 */
#define XP_LOG_CONSOLE   (0x0100)
#define XP_LOG_FILE      (0x0200)
#define XP_LOG_SYSLOG    (0x0400)

/*
 * MACROS: priority
 * - XP_LOG_PANIC
 * - XP_LOG_ALERT
 * - XP_LOG_CRITICAL
 * - XP_LOG_ERROR
 * - XP_LOG_WARNING
 * - XP_LOG_NOTICE
 * - XP_LOG_INFO
 * - XP_LOG_DEBUG
 */
#define XP_LOG_PANIC    0
#define XP_LOG_ALERT    1
#define XP_LOG_CRITICAL 2
#define XP_LOG_ERROR    3
#define XP_LOG_WARNING  4
#define XP_LOG_NOTICE   5
#define XP_LOG_INFO     6
#define XP_LOG_DEBUG    7

/*
 * MACRO: XP_LOG_ENABLED
 *
 * PARAMETERS:
 * log - log object
 * pri - one of the <priority> values
 */
#define XP_LOG_ENABLED(log,pri)((pri) <= ((log)->type & 0x00FF)) 

/*
 * MACROS: XP_LOG0 (log,ident,pri,fmt,...)
 *
 * PARAMETERS:
 * log - log object
 * ident - identifier
 * pri - one of the <priority> values
 * fmt - format used by <xp_printf>
 */
#define XP_LOG0(log,ident,pri,fmt) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt); \
	} while (0)

#define XP_LOG1(log,ident,pri,fmt,m1) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1); \
	} while (0)
#define XP_LOG2(log,ident,pri,fmt,m1,m2) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2); \
	} while (0)
#define XP_LOG3(log,ident,pri,fmt,m1,m2,m3) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3); \
	} while (0)
#define XP_LOG4(log,ident,pri,fmt,m1,m2,m3,m4) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3, m4); \
	} while (0)
#define XP_LOG5(log,ident,pri,fmt,m1,m2,m3,m4,m5) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3, m4, m5); \
	} while (0)

#define XP_LOG6(log,ident,pri,fmt,m1,m2,m3,m4,m5,m6) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3, m4, m5, m6); \
	} while (0)

#define XP_LOG7(log,ident,pri,fmt,m1,m2,m3,m4,m5,m6,m7) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3, m4, m5, m6, m7); \
	} while (0)

#define XP_LOG8(log,ident,pri,fmt,m1,m2,m3,m4,m5,m6,m7,m8) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3, m4, m5, m6, m7, m8); \
	} while (0)

#define XP_LOG9(log,ident,pri,fmt,m1,m2,m3,m4,m5,m6,m7,m8,m9) \
	do { \
		if (XP_LOG_ENABLED(log,pri)) \
			xp_log_report (log, ident, pri, fmt, m1, m2, m3, m4, m5, m6, m7, m8, m9); \
	} while (0)

/*
 * TYPE: xp_log_t
 */
struct xp_log_t
{
	int type; 

	struct {
		xp_char_t file[XP_PATH_MAX + 1];
#ifdef _WIN32
		/* TODO: xp_handle_t console;*/
#endif
	} target;

	xp_char_t ident[XP_LOG_IDENT_MAX + 1];
	xp_mtx_t mtx;

#ifndef _WIN32
	int syslog_facility;
#endif
	xp_bool_t __dynamic;
};

typedef struct xp_log_t xp_log_t;

#ifdef __cplusplus
extern "C" {
#endif

/*
 * FUNCTION: xp_log_open
 * Allocates and/or initializes an xp_log_t object.
 * If *log* is XP_NULL, it allocates a new xp_log_t object.
 *
 * PARAMETERS:
 * x - xxx
 * y - kdsajflkdsj
 *
 * RETURNS:
 * The address of the xp_log_t object allocated or initialized on success
 * XP_NULL in case of insufficient memory
 * 
 * SEE ALSO:
 * <xp_log_open>
 */
xp_log_t* xp_log_open (xp_log_t* log, const xp_char_t* ident, int type, ...);

/*
 * FUNCTION: xp_log_close
 * 
 * PARAMETERS:
 * log - log object
 */
void xp_log_close (xp_log_t* log);

/*
 * FUNCTION: xp_log_clear
 */
int xp_log_clear (xp_log_t* log);

/* 
 * FUNCTION: xp_log_setident
 */
void xp_log_set_ident (xp_log_t* log, const xp_char_t* ident);

/* 
 * FUNCTION: xp_log_settarget
 */
void xp_log_settarget (xp_log_t* log, int type);

/* 
 * FUNCTION: xp_log_settargetfile
 */
void xp_log_settargetfile (xp_log_t* log, const xp_char_t* file);

/*
 * FUNCTION: xp_log_setpriority
 */
void xp_log_setpriority (xp_log_t* log, int priority);

/*
 * FUNCTION: xp_log_setprioritybyname
 */
int xp_log_setprioritybyname (xp_log_t* log, const xp_char_t* name);

/*
 * FUNCTION: xp_log_setsyslogfacility
 */
void xp_log_setsyslogfacility (xp_log_t* log, int facility);

/* 
 * FUNCTION: xp_log_getpriority 
 */
int xp_log_getpriority (xp_log_t* log);

/*
 * FUNCTION: xp_log_getpriorityname
 */
const xp_char_t* xp_log_getpriorityname (xp_log_t* log);

/* 
 * FUNCTION: xp_log_gettarget 
 */
int xp_log_gettarget (xp_log_t* log);

/*
 * FUNCTION: xp_log_report
 */
int xp_log_report (xp_log_t* log, 
	const xp_char_t* ident, int pri, const xp_char_t* fmt, ...);

/*
 * FUNCTION: xp_getlogpriorityname
 */
const xp_char_t* xp_getlogpriorityname (int pri);

#ifdef __cplusplus
}
#endif

#endif
